#include <iostream>

using namespace std;

struct Animal {
    int age;
    string name;

    Animal() {  // 无参构造函数
        cout << "No-args Constructor" << endl;
        age = -1;
        name = "Unknown";
    }

    Animal(string name, int age):Animal() { // 有参构造函数
        cout << "Argumenting Constructor" << endl;
        this->name = name;
        this->age = age;
    }

    Animal(int i1, string i2):Animal(i2,i1) { // 有参构造函数
        cout << "Init list Constructor" << endl;
    }

    Animal(const Animal &other):Animal(other.name,other.age) { // 拷贝构造函数
        cout << "Copy constructor" << endl;
        this->name = other.name;
        this->age = other.age;
    }

    Animal& operator=(const Animal &other) { // 赋值函数
        cout << "Assigning" << endl;
        this->name = other.name;
        this->age = other.age;
    }

    ~Animal() {
        cout << "Destructor" << endl;
    }

    friend ostream& operator<<(ostream &out, const Animal &animal) {
        out << "Animal[" << animal.name << "]: " << "age=" << animal.age;
        return out;
    }
};


int main() {


    //-----------------无参构造函数-----------------------
    cout<<"------------无参构造函数------------"<<endl;
    Animal animal01; // 虽然不是很明显，但是这里不是使用指针，而是直接操作实例，所以这里实际上调用了无参构造函数。
    cout << animal01 << endl;
    /*
      输出：
        No-args Constructor
        Animal[Unknown]: age=-1
    */

    cout<<"------------无参构造函数1------------"<<endl;
    Animal animal02(); // 这并不能调用无参构造函数！编译器会当作是某个函数的声明，所以下面输出的1也许是函数的地址（暂时没有深究）。
    cout << animal02 << endl;
    /*
      输出：
        1
    */

    cout<<"------------无参构造函数2------------"<<endl;
    Animal animal03 = Animal();
    // 注意，这里可能有人会认为：等号右边调用了默认构造函数，然后因为赋值给左边所以又调用了一次拷贝构造函数，就会认为这样子会白白浪费掉一个实例。
    // 实际上，根据输出可以看到，结果并不是上述那样，而是这个语句整体上只调用了一次无参构造函数。即与“Animal animal03;”效果一样。
    cout << animal03 << endl;
    /*
      输出：
        No-args Constructor
        Animal[Unknown]: age=-1
    */

    //----------------------------------------------




    //-----------------有参构造函数-----------------------
    cout<<"------------带参构造函数1------------"<<endl;
    Animal animal001("Lion", 1);
    cout << animal001 << endl;
    /*
      输出：
        Argumenting Constructor
        Animal[Lion]: age=1
    */

    cout<<"------------带参构造函数2------------"<<endl;
    Animal animal002 = Animal("Lion", 1);
    // 这里同上面所说的，整体上仅仅调用了一次有参构造函数。
    cout << animal002 << endl;
    /*
      输出：
        Argumenting Constructor
        Animal[Lion]: age=1
    */

    //----------------------------------------------




    //----------------拷贝构造函数-------------------
    cout<<"------------拷贝构造函数------------"<<endl;
    Animal animal0001 = animal001;
    // 这里要区分“拷贝构造函数”和“赋值函数”的调用时机。前者是声明和赋值在同一行，后者不是。所以这里属于拷贝构造函数。
    cout << animal0001 << endl;
    /*
      输出：
        Copy constructor
        Animal[Lion]: age=1
    */

    //-------------------------------------------




    //------------------赋值函数------------------------
    cout<<"------------赋值函数------------"<<endl;
    Animal animal;
    animal = animal0001;
    // 因为这里animal的声明和赋值不在同一行，所以编译器会认为不是拷贝构造，而是一般的赋值语句。
    cout << animal << endl;
    /*
      输出：
        No-args Constructor
        Assigning
        Animal[Lion]: age=1
    */

    //-----------------------------------
    cout<<"-----------委托构造函数-------------"<<endl;
    Animal initlist(1,"dengs");
    cout<<initlist<<endl;
    return 0;
}